﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////

// std headers
#include <fstream>

// Qt headers
#include <QLabel>
#include <QFutureWatcher>
#include <QtConcurrent>
#include <QHBoxLayout>
#include <QPainter>
#include <QApplication>

// Gmep headers
#include "PreviewControlInterface.h"
#include "GbmpNew.h"
// custom headers
#include "Gac3DViewer.h"
#include "TranslatorManager.h"
#include "DebugMessage.h"
#include "QPixmap.h"
#include "DebugMode.h"
#include "GbmpFileSystem.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h" 

EXPOSE_DEBUG_MODE_EXPORT(GmepEnableComponentPreview, GMEP_PREVIEW_CONTROL_EXPORT);

namespace gmepgcs
{
    Gac3DViewer::Gac3DViewer(QWidget *parent)
        : QLabel(parent),
        m_pWatcher(nullptr),
        m_currentGacFilePath(),
        m_currentParameters(),
        m_candidateGacFilePath(),
        m_candidateParameters(),
        m_showTip(true),
        m_pTipLabel(nullptr)
    {
        Init();
    }

    Gac3DViewer::~Gac3DViewer()
    {
    }

    void Gac3DViewer::Clear()
    {
        if (m_spPreviewControlInterface)
        {
            m_spPreviewControlInterface->ClearSceneNode();
        }
    }

    bool Gac3DViewer::ShowTip()
    {
        return m_showTip;
    }

    void Gac3DViewer::SetShowTip(bool show)
    {
        m_showTip = show;
    }

    void Gac3DViewer::HandleFinished()
    {
        if (m_showTip)
        {
            DBG_WARN_AND_RETURN_VOID_UNLESS(m_pTipLabel, L"m_pTipLabel为空", L"GMEP", L"2024-01-30");
            m_pTipLabel->setVisible(false);
        }

        emit Finished(m_currentGacFilePath, m_currentParameters);

        if (!m_candidateGacFilePath.empty())
        {
            std::wstring gacFilePath = m_candidateGacFilePath;
            std::wstring parameters = m_candidateParameters;
            m_candidateGacFilePath = std::wstring();
            m_candidateParameters = std::wstring();

            DisplayAsync(gacFilePath, parameters);
        }
    }
    
    void Gac3DViewer::Display(std::wstring gacFilePath, std::wstring parameters)
    {
        if (gacFilePath.empty())
        {
            return;
        }

        if (!(CheckFile(gacFilePath)))
        {
            return;
        }

        if (!DEBUG_MODE(GmepEnableComponentPreview))
        {
            size_t pointIndex = gacFilePath.find_last_of('.');
            std::wstring pngFilePath = gacFilePath.substr(0, pointIndex);
            pngFilePath += L"_3D.png";
            gcmp::FileInfo fileInfo(pngFilePath);
            if (fileInfo.Exists())
            {
                QImage qImage(QString::fromStdWString(pngFilePath));
                setPixmap(QPixmap::fromImage(qImage));
                setAlignment(Qt::AlignmentFlag::AlignCenter);
            }

            return;
        }

        if (!(m_spPreviewControlInterface))
        {
            return;
        }

        int errorStats = 0;
        if (parameters.empty())
        {
            m_spPreviewControlInterface->LoadGacFile(gacFilePath, errorStats);
        }
        else
        {
            m_spPreviewControlInterface->LoadGacFile(gacFilePath, errorStats, parameters);
        }
    }

    void Gac3DViewer::DisplayAsync(std::wstring gacFilePath, std::wstring parameters)
    {
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_pWatcher, L"m_pWatcher为空", L"GMEP", L"2024-01-30");
        if (!m_pWatcher->isFinished())
        {
            m_candidateGacFilePath = gacFilePath;
            m_candidateParameters = parameters;
            return;
        }

        if (m_showTip)
        {
            DBG_WARN_AND_RETURN_VOID_UNLESS(m_pTipLabel, L"m_pTipLabel为空", L"GMEP", L"2024-01-30");
            m_pTipLabel->setVisible(true);
        }

        m_currentGacFilePath = gacFilePath;
        m_currentParameters = parameters;
        QFuture<void> future = QtConcurrent::run([=]() {Display(m_currentGacFilePath, m_currentParameters); });
        m_pWatcher->setFuture(future);
    }
    
    void Gac3DViewer::Init()
    {
        m_pWatcher = NEW_AS_QT(QFutureWatcher<void>,this);
        connect(m_pWatcher, &QFutureWatcher<void>::finished, this, &Gac3DViewer::HandleFinished);

        if (DEBUG_MODE(GmepEnableComponentPreview))
        {
            setAttribute(Qt::WA_PaintOnScreen);
            setAttribute(Qt::WA_NoSystemBackground);
            setAutoFillBackground(true);

            HWND winId = reinterpret_cast<HWND>(this->winId());
            m_spPreviewControlInterface = std::make_shared<gmep::PreviewControlInterface>(winId);

            m_pTipLabel = NEW_AS_QT_CHILD(QLabel, QString::fromStdWString(GBMP_TR(L"加载中...")), this);
        }
        else
        {
            m_spPreviewControlInterface = nullptr;
            m_pTipLabel = NEW_AS_QT_CHILD(QLabel, QString::fromStdWString(GBMP_TR(L"")), this);
        }

        DBG_WARN_AND_RETURN_VOID_UNLESS(m_pTipLabel, L"m_pTipLabel为空", L"GMEP", L"2024-01-30");
        m_pTipLabel->setSizePolicy(QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Expanding);
        m_pTipLabel->setAlignment(Qt::AlignCenter);
        m_pTipLabel->setAutoFillBackground(true);

        if (DEBUG_MODE(GmepEnableComponentPreview))
        {
            m_pTipLabel->setStyleSheet("QLabel{"
                "background-color:rgba(184, 219, 215, 255);"
                "}"
            );
        }

        m_pTipLabel->setVisible(false);

        QHBoxLayout *pTipLayout = NEW_AS_QT_CHILD(QHBoxLayout, this);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pTipLayout, L"pTipLayout为空", L"GMEP", L"2024-01-30");
        pTipLayout->setContentsMargins(0, 0, 0, 0);
        pTipLayout->setSpacing(0);
        pTipLayout->setAlignment(Qt::AlignCenter);
        pTipLayout->addWidget(m_pTipLabel);
        
        setLayout(pTipLayout);
    }

    bool Gac3DViewer::CheckFile(std::wstring filePath)
    {
        std::fstream testFile;
        testFile.open(filePath, std::ios::in);
        if (!testFile)
        {
            return false;
        }
        testFile.close();
        return true;
    }
}